/*
  RCSwitch - Arduino libary for remote control outlet switches
  Copyright (c) 2011 Suat �zg�r.  All right reserved.
  
  Contributors:
  - Andre Koehler / info(at)tomate-online(dot)de
  - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
  - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
  - Dominik Fischer / dom_fischer(at)web(dot)de
  - Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
  - Andreas Steinel / A.<lastname>(at)gmail(dot)com
  
  Project home: http://code.google.com/p/rc-switch/

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "RCSwitch.h"

#if not defined( RCSwitchDisableReceiving )
unsigned int RCSwitch::nReceivedCodeLen = 0;
unsigned int RCSwitch::nReceivedDelay = 0;
unsigned int RCSwitch::nReceivedProtocol = 0;
unsigned int RCSwitch::nChangeCount = 0;
int RCSwitch::nReceiveTolerance = 60;
char RCSwitch::nReceivedCode[65] = {0};
char RCSwitch::nReceivedCodeDesc[20] = {0};
bool RCSwitch::bAvailable = false;
#endif
unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];

RCSwitch::RCSwitch() {
  this->nTransmitterPin = -1;
  this->setRepeatTransmit(10);
  this->setProtocol(0);
#if not defined( RCSwitchDisableReceiving )
  this->nReceiverInterrupt = -1;
  this->setReceiveTolerance(60);
  RCSwitch::nChangeCount = 0;
#endif
}

/**
 * Sets the protocol to send.
 * TODO: Encoding!!
 */
void RCSwitch::setProtocol(int nProtocol) {
  this->nProtocol = nProtocol;
  if (nProtocol == 1){ // PT2260
    this->setPulseLength(450);
  }
  else if (nProtocol == 2){ // EV1527
    this->setPulseLength(350);
  }
  else if (nProtocol == 3) {
    this->setPulseLength(650);
  }
  else if (nProtocol == 4) {
    this->setPulseLength(100);
  }
  else if (nProtocol == 5) {
    this->setPulseLength(MC145026_PULSE);
  }
  else if (nProtocol == 6) {
    this->setPulseLength(NEXA_PULSE);
  }
}

/**
 * Sets the protocol to send with pulse length in microseconds.
 */
void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
  this->nProtocol = nProtocol;
  this->setPulseLength(nPulseLength);
}


/**
 * Sets pulse length in microseconds
 */
void RCSwitch::setPulseLength(int nPulseLength) {
  this->nPulseLength = nPulseLength;
}

/**
 * Sets Repeat Transmits
 */
void RCSwitch::setRepeatTransmit(int nRepeatTransmit) {
  this->nRepeatTransmit = nRepeatTransmit;
}


/**
 * Enable transmissions
 *
 * @param nTransmitterPin    Arduino Pin to which the sender is connected to
 */
void RCSwitch::enableTransmit(int nTransmitterPin) {
  this->nTransmitterPin = nTransmitterPin;
  pinMode(this->nTransmitterPin, OUTPUT);
}

/**
 * Disable transmissions
 */
void RCSwitch::disableTransmit() {
  this->nTransmitterPin = -1;
}


void RCSwitch::send(unsigned long Code, unsigned int length) {
  this->sendEx( this->dec2binWzerofill(Code, length) );
}

void RCSwitch::send(unsigned long long Code, unsigned int length) {
  this->sendEx( this->dec2binWzerofill(Code, length) );
}



void RCSwitch::sendEx(char* code) {
  
   for (int i=0; i<nRepeatTransmit; i++) {
      if (nProtocol == 1){
        sendProtocol1_01F(code);
      }
      else if (nProtocol == 2){
        sendProtocol2_01(code);
      }
      else if (nProtocol == 3){
         sendProtocol3_01(code);
      }
      else if (nProtocol == 4){
         sendProtocol4_01(code);
      }
      else if (nProtocol == 5){ // MC145026
        sendProtocol5_01F(code);
      }
      else if (nProtocol == 6){ // Nexa \CoCo
        sendProtocol6_012(code);
      }
  }
}



#define PT2260_PULSE 461    //TODO: sjekk med rcswitch
//http://www.princeton.com.tw/Portals/0/Product/PT2260_4.pdf

/**
 * PT2060
 * 24 chars (bits). One bit = 4 pulses.
 */
void RCSwitch::sendProtocol1_01F(char* code) {
  
  int i = 0;
  while (code[i] != '\0') 
  {
    switch(code[i]) 
    {
    case '0': //  H___H___
      this->transmit(1, 3);
      this->transmit(1, 3);
      break;
    case '1': //  HHH_HHH_
      this->transmit(3, 1);
      this->transmit(3, 1);
      break;
    case 'F': //  H___HHH_
      this->transmit(1, 3);
      this->transmit(3, 1);
      break;
    }
    i++;
  }
  
  // synch (before or after??)
  this->transmit(1, 31);  
}



/**
 * EV1527
 * 24 chars (bits). One bit = 4 pulses.
 */
void RCSwitch::sendProtocol2_01(char* code) {
  
  int i = 0;
  while (code[i] != '\0') 
  {
    switch(code[i]) 
    {
    case '0': //  H___
      this->transmit(1, 3);
      break;
    case '1': //  HHH_
      this->transmit(3, 1);
      break;
    }
    i++;
  }
  
  // synch (before or after??)
  this->transmit(1, 31);  
}



/**
 * UNK. origin
 * 
 */
void RCSwitch::sendProtocol3_01(char* code) {
  
  int i = 0;
  while (code[i] != '\0') 
  {
    switch(code[i]) 
    {
    case '0': //  H__
      this->transmit(1,2);
      break;
    case '1': //  HH_
      this->transmit(2,1);
      break;
    }
    i++;
  }
  
  // synch (before or after??)
  this->transmit(1,10);
}




/**
 * UNK,
 * 
 */
void RCSwitch::sendProtocol4_01(char* code) {
  
  int i = 0;
  while (code[i] != '\0') 
  {
    switch(code[i]) 
    {
    case '0': 
      this->transmit(4,11);
      break;
    case '1':
      this->transmit(9,6);
      break;
    }
    i++;
  }
  
  // synch (before or after??)
  this->transmit(1,71);
}





// F = floating | open
void RCSwitch::sendProtocol5_01F(char* code) {
  
  int i = 0;
  while (code[i] != '\0') 
  {
    switch(code[i]) 
    {
    case '0': //  H_______H_______
      this->transmit(1, 7);
      this->transmit(1, 7);
      break;
    case '1': //  HHHHHHH_HHHHHHH_
      this->transmit(7, 1);
      this->transmit(7, 1);
      break;
    case 'F': //  HHHHHHH_H_______
      this->transmit(7, 1);
      this->transmit(1, 7);
      break;
    }
    i++;
  }
  
          
//     DelayPulses(MC145026_PULSES_PER_DIGIT * 3);
        // MC145026 has no "synch" per se, just a LOW pause:-)       

  // separator (only LOW's) (before or after??)
  this->transmit(0, MC145026_DATAGRAM_SEPARATOR_CYCLES);
}


// Nexa \ CoCo wireless power switches
// Det er 65 bits, noe som tyder på at en av dem er med i en synch...feksk den siste pulsen er med i synch for den neste
void RCSwitch::sendProtocol6_012(char* code) {
  
 //Pulse2(1, 9); // Synch: H_________    med 300 pulse
  transmit(1, 12); // Synch: H_________      med 224 pulse

  int i = 0;
  while (code[i] != '\0') 
  {
    switch(code[i]) 
    {
    case '0':
      this->sendProtocol6Pulses(1); // H____        5
      break;
    case '1':
      this->sendProtocol6Pulses(2); // H_H____      7
      break;
    case '2':
      this->sendProtocol6Pulses(3); // H_H_H____    9
      break;
    }
    i++;
  }
  
//  delayCycles(34);//NEXA_DATA_SEPARATOR);    med 300 pulse
  this->transmit(0, 46);  // med 224 pulse
}

void RCSwitch::sendProtocol6Pulses(unsigned int shortPulses)
{
  while (shortPulses-- > 0)
    this->transmit(1, 1); // H_

//  delayCycles(3);  med 300 pulse
  this->transmit(0, 6); // med 224 pulse
}


void RCSwitch::transmit(int nHighPulses, int nLowPulses) {
#if not defined ( RCSwitchDisableReceiving )
  boolean disabled_Receive = false;
  int nReceiverInterrupt_backup = nReceiverInterrupt;
#endif
  if (this->nTransmitterPin != -1) {
#if not defined( RCSwitchDisableReceiving )
    if (this->nReceiverInterrupt != -1) {
      this->disableReceive();
      disabled_Receive = true;
    }
#endif
    if (nHighPulses > 0) {
      digitalWrite(this->nTransmitterPin, HIGH);
      delayMicroseconds( this->nPulseLength * nHighPulses);
    }
    if (nLowPulses > 0) {
      digitalWrite(this->nTransmitterPin, LOW);
      delayMicroseconds( this->nPulseLength * nLowPulses);
    }
#if not defined( RCSwitchDisableReceiving )
    if(disabled_Receive){
      this->enableReceive(nReceiverInterrupt_backup);
    }
#endif
  }
}







